﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;


namespace project1
{
    public class Trumpet
    {
        #region member Variables
        private Game1 game;
        private Model model;

        private int valve1; // index to the wing 1 bone
        private int valve2; //index to the wing2 bone
        private int valve3;
        private int slide1;
        private float wingAngle = 0;// current wing deployment angle
        private float valve1Trans = 0; 
        private float valve2Trans = 0;
        private float valve3Trans = 0;
        private float slide1Trans = 0;
        private bool valve1Pressed = false;
        private bool valve2Pressed = false;
        private bool valve3Pressed = false;
        private bool slide1Pressed = false;
        private bool slide1Open = false;
        private float valveDeployTime = .3f;
        private float slideDeployTime = .6f;
        private int ammoCount = 5;

        private bool deployed = false;

        /// <summary>
        /// Current position
        /// </summary>
        private Vector3 position = Vector3.Zero;

        /// <summary>
        /// how fast we are going(cm/sec)
        /// </summary>
        private float speed = 0;

        /// <summary>
        /// Thrust in cm/sec^2
        /// </summary>
        private float thrust = 0;

        /// <summary>
        /// Decelleration due to drag
        /// </summary>
        private float Drag = 1;

        /// <summary>
        /// Maximum thrust (Cm/sec^2)
        /// </summary>
        private const float MaxThurst = 2940;

        /// <summary>
        /// The current turning rate in radians per second effectively the azimuth change rate
        /// </summary>
        private float turnRate = 0;

        /// <summary>
        /// The current elevation rate in radians per second
        /// </summary>
        private float elevationRate = 0;

        /// <summary>
        /// the current banking rate in radians per second
        /// </summary>
        private float bankingRate = 0;

        /// <summary>
        /// The maximum turning rate
        /// </summary>
        private const float MaxTurnRate = (float)MathHelper.Pi;

        /// <summary>
        /// The maximum elevation rate
        /// </summary>
        private const float MaxElevationRate = (float)MathHelper.Pi;

        /// <summary>
        /// The maximum banking rate
        /// </summary>
        private const float MaxBankingRate = (float)MathHelper.PiOver4;

        private int laserNext = 0;

        private Vector3[] laserLocs = { new Vector3(50, 0, 376.025f),
            new Vector3(50, 0, 376.025f),
            new Vector3(50, 0, 376.025f),
            new Vector3(50, 0, 376.025f)};

        private LaserFire laserFire;

        /// <summary>
        /// Ship orientation as a quaternion
        /// </summary>
        Quaternion orientation = Quaternion.Identity;

        //private Cue engineSound = null;

        

        #endregion

        #region properties
        public bool Deployed { get { return deployed; } set { deployed = value; } }
        public bool Valve1Pressed { get { return valve1Pressed; } set { valve1Pressed = value; } }
        public bool Valve2Pressed { get { return valve2Pressed; } set { valve2Pressed = value; } }
        public bool Valve3Pressed { get { return valve3Pressed; } set { valve3Pressed = value; } }
        public bool Slide1Pressed { get { return slide1Pressed; } set { slide1Pressed = value; } }
        public int AmmoCount { get { return ammoCount; } set { ammoCount = value; } }

        /// <summary>
        /// The current ship thrust
        /// </summary>
        public float Thrust { get { return thrust; } set { thrust = value; } }

        /// <summary>
        /// Turning rate in radians per second
        /// </summary>
        public float TurnRate { get { return turnRate; } set { turnRate = value; } }

        public float ElevationRate { get { return elevationRate; } set { elevationRate = value; } }

        public float BankingRate { get { return bankingRate; } set { bankingRate = value; } }

        public Vector3 Position { get { return position; } set { position = value; } }

        /// <summary>
        /// The current ship transformation
        /// </summary>
        public Matrix Transform
        {
            get
            {
                return Matrix.CreateFromQuaternion(orientation) *
                    Matrix.CreateTranslation(position);
            }
        }

        
        public LaserFire LaserFire { get { return laserFire; } }

   

        /// <summary>
        /// Access to the underlying Xwing model
        /// </summary>
        public Model Model { get { return model; } }

        

        #endregion

        public Trumpet(Game1 game)
        {
            this.game = game;
            laserFire = new LaserFire(game);
        }

        public void Reset()
        {

            position = new Vector3(0, 0, 0);
            speed = 0;
            thrust = 0;
            wingAngle = 0;
            laserNext = 0;
            laserFire.LaserBlasts.Clear();
        }

        /// <summary>
        /// This function is called to load content into this component of our game.
        /// </summary>
        /// <param name="content">The content manager to load from</param>
        public void LoadContent(ContentManager content)
        {
            model = content.Load<Model>("Trumpet");

            valve1 = model.Bones.IndexOf(model.Bones["Valve1"]);
            valve2 = model.Bones.IndexOf(model.Bones["Valve2"]);
            valve3 = model.Bones.IndexOf(model.Bones["Valve3"]);
            slide1 = model.Bones.IndexOf(model.Bones["Slide1"]); //Z -9

            laserFire.LoadContent(content);
    


        }

        /// <summary>
        /// This function is called to update this component of our game to the current game time.
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {

            float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;

            // 
            // Orientation updates
            //

            
            float turnAngle = turnRate * MaxTurnRate * delta;
            orientation *= Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), turnAngle);//Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), -turnAngle);// *
                           //Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), turnAngle);
            orientation *= Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), elevationRate * MaxElevationRate * delta);
            orientation.Normalize();
            

            //
            // Position updates
            //

            float acceleration = thrust * MaxThurst - Drag * speed;
            speed += acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;

            Matrix transform = Matrix.CreateFromQuaternion(orientation);

            Vector3 directedThrust = Vector3.TransformNormal(new Vector3(0, 0, 1), transform);
            position += directedThrust * speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

            float wingDeployTime = 2.0f;


            laserFire.Update(gameTime);

            /*
            if (thrust > 0)
            {
                if (engineSound == null)
                {
                    engineSound = game.SoundBank.GetCue("engine_2");
                    engineSound.Play();
                }

                else if (engineSound.IsPaused)
                {
                    engineSound.Resume();
                }
            }
            else
            {
                if (engineSound != null && engineSound.IsPlaying)
                {
                    engineSound.Pause();
                }
            }
            */

            //VALVE update
            //valve one pressed or not pressed(up or down)
            if (Valve1Pressed)
            {
                valve1Trans -= (float)(2 * delta / valveDeployTime);
                if (valve1Trans < -2)
                {
                    valve1Trans = -2;
                    valve1Pressed = false;
                }
            }
            if (!Valve1Pressed)
            {
                valve1Trans += (float)(2 * delta / valveDeployTime);
                if (valve1Trans > 0)
                    valve1Trans = 0;
            }

            //valve two pressed or not pressed(up or down)
            if (Valve2Pressed)
            {
                valve2Trans -= (float)(2 * delta / valveDeployTime);
                if (valve2Trans < -2)
                {
                    valve2Trans = -2;
                    valve2Pressed = false;
                }
            }
            if (!Valve2Pressed)
            {
                valve2Trans += (float)(2 * delta / valveDeployTime);
                if (valve2Trans > 0)
                    valve2Trans = 0;
            }

            //valve three pressed or not pressed(up or down)
            if (Valve3Pressed)
            {
                valve3Trans -= (float)(2 * delta / valveDeployTime);
                if (valve3Trans < -2)
                {
                    valve3Trans = -2;
                    valve3Pressed = false;
                }
            }
            if (!Valve3Pressed)
            {
                valve3Trans += (float)(2 * delta / valveDeployTime);
                if (valve3Trans > 0)
                    valve3Trans = 0;
            }

            //slide
            if(slide1Pressed)
            {
                if (slide1Trans > -9 && !slide1Open)
                {
                    slide1Trans -= (float)(9 * delta / slideDeployTime);
                    if (slide1Trans < -9)
                    {
                        slide1Trans = -9;
                        slide1Open = true;
                    }
                }


                
                if (slide1Trans < 0 && slide1Open)
                {
                    slide1Trans += (float)(9 * delta / slideDeployTime);
                    if (slide1Trans > 0)
                    {
                        slide1Trans = 0;
                        slide1Open = false;
                        slide1Pressed = false;
                        ammoCount = 5;
                    }
                }

       
            }


      
        }

        /// <summary>
        /// This function is called to draw this game component.
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="gameTime"></param>
        public void Draw(GraphicsDeviceManager graphics, GameTime gameTime)
        {
            DrawModel(graphics, model, Matrix.CreateScale(9)*Transform);

            laserFire.Draw(graphics, gameTime);

        }

        private void DrawModel(GraphicsDeviceManager graphics, Model model, Matrix world)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);


            //transforms[wing1] = Matrix.CreateRotationY(wingAngle) * transforms[wing1];
            //transforms[wing2] = Matrix.CreateRotationY(-wingAngle) * transforms[wing2];

            transforms[valve1] = Matrix.CreateTranslation(new Vector3(0, 0, valve1Trans)) * transforms[valve1];
            transforms[valve2] = Matrix.CreateTranslation(new Vector3(0, 0, valve2Trans)) * transforms[valve2];
            transforms[valve3] = Matrix.CreateTranslation(new Vector3(0, 0, valve3Trans)) * transforms[valve3];
            transforms[slide1] = Matrix.CreateTranslation(new Vector3(0, 0, slide1Trans)) * transforms[slide1];

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.World = transforms[mesh.ParentBone.Index] * world;
                    effect.View = game.Camera.View;
                    effect.Projection = game.Camera.Projection;
                }
                mesh.Draw();
            }
        }

        public void FireLaser()
        {
            if (ammoCount <= 0)
                return;

            ammoCount--;

            //game.SoundBank.PlayCue("tx0_fire1");

            Vector3 position = Vector3.Transform(laserLocs[laserNext], Transform);

            Matrix orientation = Transform;
            orientation.Translation = new Vector3(0, 0, 0);

            laserFire.FireLaser(position, orientation, this.speed);

            Vector3 direction = Vector3.TransformNormal(new Vector3(0, 0, 1), orientation);

            laserNext = (laserNext + 1) % 4;
        }


    }
}
